package com.hifar.utils;

import MvCameraControlWrapper.MvCameraControl;
import MvCameraControlWrapper.MvCameraControlDefines;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import static MvCameraControlWrapper.MvCameraControlDefines.MV_OK;

/**
 * @DESCRIPTION:
 * @Author: shishaopeng
 * @Date: 2022/11/30
 * @Version: v1.0
 */
public class RecordThread extends Thread {


    private MvCameraControlDefines.Handle hCamera;

    private OneFrameData oneFrameData;

    private AtomicBoolean isGrabbing = new AtomicBoolean(false);

    private AtomicInteger activeCount = new AtomicInteger(0);

    private AtomicBoolean isRecording = new AtomicBoolean(false);;


    public void setIsRecording(Boolean changeRecord) {
        this.isRecording.set(changeRecord);
    }

    public void takePhoto(String imgName, String imgPath) {
        byte[] pData = null;
        MvCameraControlDefines.MV_FRAME_OUT_INFO stImageInfo = null;

        int times = 0;
        while (oneFrameData == null && times <= 10) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            times++;
        }

        synchronized (oneFrameData) {
            stImageInfo = oneFrameData.getStImageInfo();
            pData = oneFrameData.getpData();
        }
        int imageLen = stImageInfo.width * stImageInfo.height * 3;    // Every RGB pixel takes 3 bytes
        byte[] imageBuffer = new byte[imageLen];

        // Call MV_CC_SaveImage to save image as JPEG
        MvCameraControlDefines.MV_SAVE_IMAGE_PARAM stSaveParam = new MvCameraControlDefines.MV_SAVE_IMAGE_PARAM();
        stSaveParam.width = stImageInfo.width;                                  // image width
        stSaveParam.height = stImageInfo.height;                                // image height
        stSaveParam.data = pData;                                               // image data
        stSaveParam.dataLen = stImageInfo.frameLen;                             // image data length
        stSaveParam.pixelType = stImageInfo.pixelType;                          // image pixel format
        stSaveParam.imageBuffer = imageBuffer;                                  // output image buffer
        stSaveParam.imageType = MvCameraControlDefines.MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg;               // output image pixel format
        stSaveParam.methodValue = 0;                                            // Interpolation method that converts Bayer format to RGB24.  0-Neareast 1-double linear 2-Hamilton
        stSaveParam.jpgQuality = 60;                                            // JPG endoding quality(50-99]

        int nRet = MvCameraControl.MV_CC_SaveImage(hCamera, stSaveParam);
        if (MV_OK != nRet)
        {
            System.err.printf("SaveImage fail, errcode: [%#x]\n", nRet);
            throw new RuntimeException("保存图片失败！");
        }

        // Save buffer content to file
        CameraUtils.saveDataToFile(imageBuffer, stSaveParam.imageLen, String.format("%s.jpeg", imgName), imgPath);
    }

    @Override
    public void run() {
//        MvCameraControlDefines.MV_FRAME_OUT frameOut = new MvCameraControlDefines.MV_FRAME_OUT();
//        MvCameraControlDefines.MV_CC_INPUT_FRAME_INFO frameInfo = new MvCameraControlDefines.MV_CC_INPUT_FRAME_INFO();
//
//        while (true) {
//            int ret = MvCameraControl.MV_CC_GetImageBuffer(hCamera, frameOut, 1000);
//            if (MV_OK == ret && frameOut.buffer != null) {
//                System.out.printf("get one frame: width:%s, height: %s, nFrameNum: %s",
//                        frameOut.mvFrameOutInfo.width, frameOut.mvFrameOutInfo.height, frameOut.mvFrameOutInfo.frameNum);
//                frameInfo.pData = frameOut.buffer;
//                frameInfo.nDataLen = frameOut.mvFrameOutInfo.frameLen;
//                ret = MvCameraControl.MV_CC_InputOneFrame(hCamera, frameInfo);
//                if (MV_OK != ret) {
//                    System.err.printf("input one frame fail! , errcode: [%#x]\n", ret);
//                }
//                ret = MvCameraControl.MV_CC_FreeImageBuffer(hCamera, frameOut);
//            } else {
//                System.err.printf("no data , errcode: [%#x]\n", ret);
//            }
//            if (!isRecording) {
//                break;
//            }
//        }


        MvCameraControlDefines.MV_CC_INPUT_FRAME_INFO frameInfo = new MvCameraControlDefines.MV_CC_INPUT_FRAME_INFO();
        while (true) {
            if (isInterrupted()) {
                return;
            }
            MvCameraControlDefines.MVCC_INTVALUE stParam = new MvCameraControlDefines.MVCC_INTVALUE();
            int nRet = MvCameraControl.MV_CC_GetIntValue(hCamera, "PayloadSize", stParam);
            if (MV_OK != nRet)
            {
                System.err.printf("Get PayloadSize fail, errcode: [%#x]\n", nRet);
                break;
            }

            MvCameraControlDefines.MV_FRAME_OUT_INFO stImageInfo = new MvCameraControlDefines.MV_FRAME_OUT_INFO();
            byte[] pData = new byte[(int)stParam.curValue];
            nRet = MvCameraControl.MV_CC_GetOneFrameTimeout(hCamera, pData, stImageInfo, 1000);

            if (MV_OK == nRet && pData.length != 0) {
                System.out.printf("get one frame: width:%s, height: %s, nFrameNum: %s",
                        stImageInfo.width, stImageInfo.height, stImageInfo.frameNum);

                if (isRecording.get()) {
                    // 网视频文件写入数据
                    frameInfo.pData = pData;
                    frameInfo.nDataLen = stImageInfo.frameLen;
                    nRet = MvCameraControl.MV_CC_InputOneFrame(hCamera, frameInfo);
                    if (MV_OK != nRet) {
                        System.err.printf("input one frame fail! , errcode: [%#x]\n", nRet);
                    }
                } else {
                    break;
                }

                oneFrameData = new OneFrameData(pData, stImageInfo);
//                ret = MvCameraControl.MV_CC_FreeImageBuffer(hCamera, frameOut);
            } else {
                System.err.printf("no data , errcode: [%#x]\n", nRet);
            }

        }

    }


    public MvCameraControlDefines.Handle gethCamera() {
        return hCamera;
    }

    public void sethCamera(MvCameraControlDefines.Handle hCamera) {
        this.hCamera = hCamera;
    }

    public OneFrameData getOneFrameData() {
        return oneFrameData;
    }

    public void setOneFrameData(OneFrameData oneFrameData) {
        this.oneFrameData = oneFrameData;
    }

    public AtomicBoolean getIsRecording() {
        return isRecording;
    }

    public AtomicBoolean getIsGrabbing() {
        return isGrabbing;
    }

    public void setIsGrabbing(Boolean isGrabbing) {
        this.isGrabbing.set(isGrabbing);
    }

    public void plusActiveCount() {
        activeCount.incrementAndGet();
    }

    public Integer minusActiveCount() {
        return activeCount.decrementAndGet();
    }

}
